#include "uart.h"

static constexpr const char *TAG = "App_uart";

namespace app
{
    void uart::start()
    {
        uart_config_t uart_config = {
            .baud_rate = 115200,
            .data_bits = UART_DATA_8_BITS,
            .parity = UART_PARITY_DISABLE,
            .stop_bits = UART_STOP_BITS_1,
            .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
            .source_clk = UART_SCLK_DEFAULT,
        };
        uart_param_config(uart_num, &uart_config);
        uart_set_pin(uart_num, tx_pin, rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
        uart_driver_install(uart_num, 256, 256, 0, NULL, 0);


        xTaskCreate(
            [](void *a)
            {
                auto self = static_cast<uart *>(a);

                //ESP_LOGI(TAG, "uart %d recv task start", self->uart_num);

                for (;;)
                {
                    size_t len;

                    esp_err_t err = uart_get_buffered_data_len(self->uart_num, &len);
                    if (err == ESP_OK && len > 0)
                    {
                        void *rx_buffer = heap_caps_malloc(len, MALLOC_CAP_DEFAULT);
                        if (!rx_buffer)
                        {
                            ESP_LOGE(TAG, "uart %d malloc %d bytes failed", self->uart_num, len);
                            continue;
                        }
                        uart_read_bytes(self->uart_num, rx_buffer, len, portMAX_DELAY);
                        if (self->receive_callback)
                        {
                            self->receive_callback((const char *)rx_buffer, len);
                        }
                        heap_caps_free(rx_buffer);
                    }
                    else
                    {
                       // ESP_LOGW(TAG, "uart %d get buffered data len failed: %s", self->uart_num, esp_err_to_name(err));
                        vTaskDelay(pdMS_TO_TICKS(10));
                    }
                }

                vTaskDelete(nullptr);
            },
            "uart recv task",
            1024 * 6,
            this,
            15,
            nullptr);
    }
    void uart::stop()
    {
    }
    void uart::onReceive(std::function<void(const char *, size_t len)> callback)
    {
        receive_callback = callback;
    }

    void uart::send(const char *data, size_t len)
    {
        uart_write_bytes(uart_num, data, len);
    }
    void uart::send(const std::string &data)
    {
        uart_write_bytes(uart_num, data.c_str(), data.size());
    }
}
